package edu.pku.taas.hyperic.types2;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

import org.apache.xmlrpc.XmlRpcException;

import com.xensource.xenapi.Connection;
import com.xensource.xenapi.Host;
import com.xensource.xenapi.VM;
import com.xensource.xenapi.VMGuestMetrics;
import com.xensource.xenapi.Types.BadServerResponse;

import edu.pku.taas.hyperic.monitor.MonitorConfigureManager;
import edu.pku.taas.hyperic.monitor.MonitorConstants;

public class XenManager {
	static final String PROP_URL = "url";
	static final String PROP_USERNAME = "PROP_USERNAME";
	static final String PROP_PASSWORD = "PROP_PASSWORD";
	static final String[] CONNECT_PROPS = { PROP_URL, PROP_USERNAME, PROP_PASSWORD };
	static final String VM_IP_KEY = "0/ip";

	static Map<String, MachineInfo> name2MachineInfo = new HashMap<String, MachineInfo>();
	static Map<String, List<MachineInfo>> pmName2VMMachineInfoList = new HashMap<String, List<MachineInfo>>();

	public List<MachineInfo> getVMMachineInfoList(String pmName) {
		return pmName2VMMachineInfoList.get(pmName);
	}

	public XenManager() {
		try {
			initialXenPoolInfo();
		} catch (Exception e) {
			System.out.println("error to get vm info from Xen Server.");
			e.printStackTrace();
			throw new RuntimeException(e.getMessage());
		}
	}

	public MachineInfo getMachineInfo(String vmrName) {
		MachineInfo r = null;
		for (Map.Entry<String, MachineInfo> m : name2MachineInfo.entrySet()) {
			if (m.getKey().contains(vmrName) || vmrName.contains(m.getKey()))
				r = m.getValue();
		}
		return r;
	}

	private void initialXenPoolInfo() throws Exception, BadServerResponse, XmlRpcException {
		int clusterNum = MonitorConfigureManager.getIntConfigure(MonitorConstants.CLUSTER_NUM);
		for (int i = 1; i <= clusterNum; i++) {
			String clusterMasterIP = MonitorConfigureManager.getStringConfigure(MonitorConstants.CLUSTER_MASTER_IP
					+ MonitorConstants.CLUSTER_CONF_SUFFIX + i);
			
			System.out.println("clusterMasterIP=" + clusterMasterIP);
//			String clusterMasterHostName = MonitorConfigureManager.getStringConfigure(MonitorConstants.CLUSTER_MASTER_HOST_NAME
//					+ MonitorConstants.CLUSTER_CONF_SUFFIX + i);
//			int clusterMasterPort = MonitorConfigureManager.getIntConfigure(MonitorConstants.CLUSTER_MASTER_PORT
//					+ MonitorConstants.CLUSTER_CONF_SUFFIX + i);
//			System.out.println("clusterMasterHostName=" + clusterMasterHostName);
//			System.out.println("clusterMasterPort=" + clusterMasterPort);

			Properties p = new Properties();
			
			p.put(PROP_URL, "http://"+clusterMasterIP);
			p.put(PROP_USERNAME, "root");
			p.put(PROP_PASSWORD, "123456");

			initialClustger(p);
		}

	}

	private void initialClustger(Properties p) throws Exception, BadServerResponse, XmlRpcException{
		Connection conn = connect(p);

		Set<Host> hosts = Host.getAll(conn);
		System.out.println("get hosts:" + hosts.size());

		PMInfo pi = null;
		VMInfo vi = null;
		List<MachineInfo> vml = null;
		for (Host h : hosts) {
			String hostIp = h.getAddress(conn);
			String hostName = h.getHostname(conn);
			String hostUUID = h.getUuid(conn);
			pi = new PMInfo();
			pi.setIp(hostIp);
			pi.setName(hostName);
			pi.setUuid(hostUUID);
			name2MachineInfo.put(hostName, pi);
			System.out.println("get a host:" + hostIp + " " + hostName);

			java.util.Set<VM> vms;
			try {
				vms = h.getResidentVMs(conn);
				String vmName = null;
				String vmIp = null;
				String vmUUID = null;
				System.out.println("get vms = " + vms.size());

				if (vms.size() > 0) {
					vml = new ArrayList<MachineInfo>();
					pmName2VMMachineInfoList.put(hostName, vml);
				}

				for (VM vm : vms) {
					try {
						vmName = vm.getNameLabel(conn);
						VMGuestMetrics vmgm = vm.getGuestMetrics(conn);
						java.util.Map<java.lang.String, java.lang.String> vmNetworks = vmgm.getNetworks(conn);
						vmIp = vmNetworks.get(VM_IP_KEY);
						vmUUID = vm.getUuid(conn);

						vi = new VMInfo();
						vi.setIp(vmIp);
						vi.setName(vmName);
						vi.setUuid(vmUUID);

						vml.add(vi);

						name2MachineInfo.put(vmName, vi);

						System.out.println("get a vm: vmIp = " + vmIp);
						System.out.println("get a vm: getNameLabel = " + vmName);
						// System.out.println("get a vm net work:"+vmNetworks);
					} catch (Exception e) {
						// do nothing,as we don't need the control domain of
						// XenServer
					}

				}
			} catch (BadServerResponse e) {
				e.printStackTrace();
			} catch (XmlRpcException e) {
				e.printStackTrace();
			}

		}

	}

	private Properties getProperties() {
		Properties p = new Properties();
		p.put(PROP_URL, "http://172.16.0.201");
		p.put(PROP_USERNAME, "root");
		p.put(PROP_PASSWORD, "123456");
		return p;
	}

	Connection connect(Properties props) throws Exception {
		String url = props.getProperty(PROP_URL);
		String username = props.getProperty(PROP_USERNAME);
		String password = props.getProperty(PROP_PASSWORD);

		try {
			return new Connection(url, username, password);
		} catch (Exception e) {
			throw new Exception("Connection error: " + e, e);
		}
	}

	/**
	 * @param args
	 * @throws Exception
	 * @throws Exception
	 */
	public static void main(String[] args) throws Exception {
		// testGetVMNetWork();
		// testControlVMStart();
		// testControlVMStop();
		new XenManager().initialXenPoolInfo();
	}
}
